package com.ysd.modules.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ysd.modules.sys.entity.Chapter;
import com.ysd.modules.sys.entity.Options;
import com.ysd.modules.sys.entity.Topic;
import com.ysd.modules.sys.dao.TopicSysDao;
import com.ysd.modules.sys.entity.TopicType;
import com.ysd.modules.sys.model.OptionsModel;
import com.ysd.modules.sys.model.TopicModel;
import com.ysd.modules.sys.model.TopicResp;
import com.ysd.modules.sys.service.ChapterService;
import com.ysd.modules.sys.service.OptionsService;
import com.ysd.modules.sys.service.TopicService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysd.modules.sys.service.TopicTypeService;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author dapeng
 * @since 2021-07-15
 */

@Service
public class TopicServiceImpl extends ServiceImpl<TopicSysDao, Topic> implements TopicService {

    @Autowired
    private OptionsService optionsService;

    @Autowired
    private TopicTypeService topicTypeService;

    @Autowired
    private ChapterService chapterService;

    @Override
    public IPage<TopicResp> listSearch(Map<String, Object> params) {
        QueryWrapper wrapper = new QueryWrapper();
        Integer page = Integer.parseInt(params.get("page").toString());
        Integer limit = Integer.parseInt(params.get("limit").toString());

        Page<Topic> currPage = new Page<>();
        currPage.setCurrent(page);
        currPage.setSize(limit);
        if (params.get("cid") != null && !params.get("cid").equals("")) {
            wrapper.eq("chapter_id", params.get("cid"));
        }
        Object title = params.get("title");
        wrapper.like("title", title == null ? "" : title);

        Object chapterName = params.get("chapterName");
        wrapper.like("chapter_name", chapterName == null ? "" : chapterName);

        wrapper.ge("status", 0);
        IPage<Topic> iPage = this.baseMapper.selectPage(currPage, wrapper);

        List<TopicResp> topicResps = iPage.getRecords().stream().map(e -> {
            TopicResp topicResp = new TopicResp();
            BeanUtils.copyProperties(e, topicResp);
            return topicResp;
        }).collect(Collectors.toList());

        topicResps = optionsService.listSearchByTopicIds(topicResps);

        topicResps = topicTypeService.listSearchByIds(topicResps);
        IPage<TopicResp> result = new Page<>();
        BeanUtils.copyProperties(iPage, result);

        result.setRecords(topicResps);

        return result;
    }

    @Override
    public Topic detailSearch(Integer id) {
        Topic topic = this.baseMapper.selectById(id);
        return topic;
    }

    @Override
    public void delete(List<Integer> ids) {
        UpdateWrapper<Topic> wrapper = new UpdateWrapper<Topic>();
        wrapper.in("id", ids);
        wrapper.set("status", 2);
        this.baseMapper.update(new Topic(), wrapper);
    }

    @Override
    @Transactional
    public void saveAll(List<TopicResp> objects, Long userId, String userName) {
        List<String> chapterNames = objects.stream().map(TopicResp::getChapterName).collect(Collectors.toList());
        QueryWrapper wrapper = new QueryWrapper();
        wrapper.select("id", "name");
        wrapper.in("name", chapterNames);
        List<Chapter> chapters = chapterService.list(wrapper);

        List<String> typeNames = objects.stream().map(TopicResp::getTypeName).collect(Collectors.toList());
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.select("id", "name");
        queryWrapper.in("name", typeNames);
        List<TopicType> topicTypes = topicTypeService.list(queryWrapper);

        for (TopicResp o : objects) {
            Topic topic = new Topic();
            BeanUtils.copyProperties(o, topic);
            topic.setStatus(1);
            topic.setCreateTime(new Date());
            topic.setCreateId(userId.intValue());
            topic.setCreateName(userName);
            Chapter first = chapters.stream().filter(c -> c.getName().equals(o.getChapterName())).findFirst().get();
            if (first != null) {
                topic.setChapterId(first.getId());
            }
            TopicType topicType = topicTypes.stream().filter(c -> c.getName().equals(o.getTypeName())).findFirst().get();
            if (topicType != null) {
                topic.setTypeId(topicType.getId());
            }
            this.save(topic);


            Options optionsA = new Options();
            optionsA.setTopicId(topic.getId());
            optionsA.setOptions("A");
            optionsA.setContent(o.getA());
            optionsA.setTopicTitle(topic.getTitle());

            Options optionsB = new Options();
            optionsB.setTopicId(topic.getId());
            optionsB.setOptions("B");
            optionsB.setContent(o.getB());
            optionsB.setTopicTitle(topic.getTitle());

            Options optionsC = new Options();
            optionsC.setTopicId(topic.getId());
            optionsC.setOptions("C");
            optionsC.setContent(o.getC());
            optionsC.setTopicTitle(topic.getTitle());

            Options optionsD = new Options();
            optionsD.setTopicId(topic.getId());
            optionsD.setOptions("D");
            optionsD.setContent(o.getD());
            optionsD.setTopicTitle(topic.getTitle());

            List<Options> optionsSave = new ArrayList<>();

            optionsService.save(optionsA);
            optionsService.save(optionsB);
            optionsService.save(optionsC);
            optionsService.save(optionsD);

            optionsSave.add(optionsA);
            optionsSave.add(optionsB);
            optionsSave.add(optionsC);
            optionsSave.add(optionsD);

            String trueAnswer = o.getTrueAnswer();
            StringBuffer trueAnswerIds = new StringBuffer("");

            if (trueAnswer.contains("A")) {
                trueAnswerIds.append(optionsA.getId() + ",");
            }
            if (trueAnswer.contains("B")) {
                trueAnswerIds.append(optionsB.getId() + ",");
            }
            if (trueAnswer.contains("C")) {
                trueAnswerIds.append(optionsC.getId() + ",");
            }
            if (trueAnswer.contains("D")) {
                trueAnswerIds.append(optionsD.getId() + ",");
            }
            trueAnswerIds.deleteCharAt(trueAnswerIds.length() - 1);

            topic.setAnswerId(trueAnswerIds.toString());
            this.updateById(topic);

        }
    }

    @Override
    public int adds(TopicModel tm, Long userId, String userName) {
        Topic topic = new Topic();
        topic.setTitle(tm.getTitle());

        topic.setTypeId(tm.getTypeId());
        topic.setLabel(tm.getLabel());
        topic.setScore(tm.getScore());
        topic.setStatus(1);
        topic.setCreateTime(new Date());
        topic.setCreateId(userId.intValue());
        topic.setCreateName(userName);
        topic.setChapterId(tm.getChapterId());

        Chapter ch = chapterService.getById(tm.getChapterId());
        topic.setChapterName(ch.getName());

        topic.setTypeId(tm.getTypeId());

        topic.setAnswerId(StringUtils.strip(tm.getAnswerId().toString(), "[]"));
        topic.setAnalysis(tm.getAnalysis());

        boolean flag = this.save(topic);
        char c = 'A';
        for (OptionsModel om : tm.getOptions()) {
            Options op = new Options();
            op.setTopicId(topic.getId());
            op.setOptions(c + "");
            op.setContent(om.getVals());
            op.setTopicTitle(topic.getTitle());
            c++;
            optionsService.save(op);
        }
        if (flag) {
            return 1;
        }
        return 0;
    }


}
